package com.jfs.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jfs.constant.CommonConstant;
import com.jfs.constant.SecurityConstant;
import com.jfs.constant.SipConstant;
import com.jfs.entity.ChannelDirectory;
import com.jfs.entity.MiddleChannelDirectory;
import com.jfs.entity.MiddleUserChannelDirectory;
import com.jfs.entity.dto.ChannelDirectoryDropListDto;
import com.jfs.entity.dto.DeviceChannelListDto;
import com.jfs.entity.vo.*;
import com.jfs.mapper.ChannelDirectoryMapper;
import com.jfs.result.Result;
import com.jfs.security.vo.LoginUserEntity;
import com.jfs.service.ChannelDirectoryService;
import com.jfs.service.MiddleChannelDirectoryService;
import com.jfs.service.MiddleUserChannelDirectoryService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @Description 设备所属目录实现
 * @E-mail cwm3412638@163.com
 * @Author cwm
 * @Date 2022/8/10
 */
@Service
@Slf4j
@AllArgsConstructor
public class DeviceDirectoryServiceImpl extends ServiceImpl<ChannelDirectoryMapper, ChannelDirectory> implements ChannelDirectoryService {
    private final MiddleChannelDirectoryService middleChannelDirectoryService;
    private final MiddleUserChannelDirectoryService middleUserChannelDirectoryService;

    /**
     * 获取当前用户所拥有通道目录下拉列表
     *
     * @param loginUserEntity
     * @return
     */
    @Override
    public List<ChannelDirectoryDropListDto> dropList(LoginUserEntity loginUserEntity, ChannelDirectoryDropListVo channelDirectoryDropListVo) {
        List<ChannelDirectoryDropListDto> result = new ArrayList<>();
        List<ChannelDirectory> channelDirectoryList = null;
        //判断用户是否属于超级管理员
        if (SecurityConstant.SUPER_ADMIN.equals(loginUserEntity.getRole().getRoleKey())) {
            //超级管理查询所有目录
            channelDirectoryList = this.list(Wrappers.<ChannelDirectory>lambdaQuery()
                    .eq(ChannelDirectory::getParentId, channelDirectoryDropListVo.getParentId())
                    .orderByDesc(ChannelDirectory::getSort)
            );
        } else {
            //非超级管理员根据自己拥有目录权限查询
            if (CommonConstant.PARENT_ID.equals(channelDirectoryDropListVo.getParentId())) {
                //如果是查询顶级目录
                channelDirectoryList = this.getBaseMapper().channelDirectoryByUserIdAndTop(loginUserEntity.getId());
            } else {
                //查询下级目录
                channelDirectoryList = this.getBaseMapper().channelDirectoryByUserIdAndParentId(loginUserEntity.getId(), channelDirectoryDropListVo.getParentId());
            }
        }
        //转换数据为dto
        if (CollectionUtil.isNotEmpty(channelDirectoryList)) {
            for (ChannelDirectory channelDirectory : channelDirectoryList
            ) {
                //获取目录所有拥有的userid ->是中间表的主键
                Set<String> userIds = Optional.ofNullable(this.middleUserChannelDirectoryService.getBaseMapper().selectList(Wrappers.<MiddleUserChannelDirectory>lambdaQuery()
                                .eq(MiddleUserChannelDirectory::getChannelDirectoryId, channelDirectory.getId())
                        ))
                        .map(List::stream)
                        .orElseGet(Stream::empty)
                        .map(MiddleUserChannelDirectory::getId)
                        .collect(Collectors.toSet());
                //获取当前目录下所有拥有的所有channelIds ->对应的是中间表的主键
                Set<String> channelIds = Optional.ofNullable(this.middleChannelDirectoryService.getBaseMapper().selectList(Wrappers.<MiddleChannelDirectory>lambdaQuery()
                                .eq(MiddleChannelDirectory::getChannelDirectoryId, channelDirectory.getId())
                        ))
                        .map(List::stream)
                        .orElseGet(Stream::empty)
                        .map(MiddleChannelDirectory::getId)
                        .collect(Collectors.toSet());
                ChannelDirectoryDropListDto channelDirectoryDropListDto = new ChannelDirectoryDropListDto();
                BeanUtil.copyProperties(channelDirectory, channelDirectoryDropListDto);
                channelDirectoryDropListDto.setUserId(userIds);
                channelDirectoryDropListDto.setChannelIds(channelIds);
                result.add(channelDirectoryDropListDto);
            }
        }
        return result;
    }

    /**
     * 添加通道目录
     *
     * @param channelDirectoryAddVo
     * @return
     */
    @Override
    @Transactional
    public Result<Object> add(ChannelDirectoryAddVo channelDirectoryAddVo) {
        ChannelDirectory channelDirectory = new ChannelDirectory();
        //顶级目录
        if (CommonConstant.PARENT_ID.equals(channelDirectoryAddVo.getParentId())) {
            channelDirectory.setLevel(1);
            BeanUtils.copyProperties(channelDirectoryAddVo, channelDirectory);
        } else {
            String parentId = channelDirectoryAddVo.getParentId();
            //非顶级目录需要算级别
            //直接查询父的级别 +1
            //设置级别
            ChannelDirectory one = this.getOne(Wrappers.<ChannelDirectory>lambdaQuery().eq(ChannelDirectory::getId, parentId));
            BeanUtils.copyProperties(channelDirectoryAddVo, channelDirectory);
            channelDirectory.setLevel(one.getLevel() + 1);
        }
        boolean save = this.save(channelDirectory);
        if (save) {
            return Result.success("添加通道目录成功", null);
        }
        return Result.failed("添加通道目录失败");
    }

    /**
     * 添加通道到目录下
     *
     * @param channelDirectoryAddChannelVo
     * @return
     */
    @Override
    @Transactional
    public Result<Object> addChannel(ChannelDirectoryAddChannelVo channelDirectoryAddChannelVo) {
        List<MiddleChannelDirectory> middleChannelDirectories = new ArrayList<>();
        for (String channelId : channelDirectoryAddChannelVo.getChannelIds()
        ) {
            MiddleChannelDirectory middleChannelDirectory = new MiddleChannelDirectory();
            middleChannelDirectory.setChannelId(channelId);
            middleChannelDirectory.setChannelDirectoryId(channelDirectoryAddChannelVo.getChannelDirectoryId());
            middleChannelDirectories.add(middleChannelDirectory);
        }
        boolean b = middleChannelDirectoryService.saveBatch(middleChannelDirectories);
        if (b) {
            return Result.success("添加通道到目录下成功", null);
        }
        return Result.failed("添加通道到目录下失败");
    }

    /**
     * 此处不需要对用户权限进行判断 在获取目录列表的接口中已经做了判断
     *
     * @param channelDirectoryListChannelVo
     * @return
     */
    @Override
    public IPage<DeviceChannelListDto> listChannel(ChannelDirectoryListChannelVo channelDirectoryListChannelVo) {
        String searchKey = null;
        //此处主要为了解决sqlite和mysql xml中函数 CONCAT 不能公用问题
        if (StrUtil.isNotEmpty(channelDirectoryListChannelVo.getSearchKey())){
            searchKey ="%%s%";
            searchKey= searchKey.replace("%s",channelDirectoryListChannelVo.getSearchKey());
        }
        return this.baseMapper.pageListChannelByDirectory(new Page<>(channelDirectoryListChannelVo.getPageNum(), channelDirectoryListChannelVo.getPageSize()),
                channelDirectoryListChannelVo.getChannelDirectoryIds(), searchKey, channelDirectoryListChannelVo.getOnline()
        );
    }

    /**
     * 分配目录给用户
     *
     * @param channelDirectoryAddToUserVo
     * @return
     */
    @Override
    @Transactional
    public Result<Object> addChannelDirectoryToUser(ChannelDirectoryAddToUserVo channelDirectoryAddToUserVo) {
        List<MiddleUserChannelDirectory> middleUserChannelDirectories = new ArrayList<>();
        for (String userId : channelDirectoryAddToUserVo.getUserIds()
        ) {
            MiddleUserChannelDirectory middleUserChannelDirectory = new MiddleUserChannelDirectory();
            middleUserChannelDirectory.setUserId(userId);
            middleUserChannelDirectory.setChannelDirectoryId(channelDirectoryAddToUserVo.getChannelDirectoryId());
            middleUserChannelDirectories.add(middleUserChannelDirectory);
        }
        boolean b = this.middleUserChannelDirectoryService.saveBatch(middleUserChannelDirectories);
        if (b) {
            return Result.success("分配目录成功", null);
        }
        return Result.failed("分配目录失败");
    }

    /**
     * 取消分配目录给用户
     *
     * @param channelDirectoryDeleteToUserVo
     * @return
     */
    @Override
    @Transactional
    public Result<Object> deleteChannelDirectoryToUser(ChannelDirectoryDeleteToUserVo channelDirectoryDeleteToUserVo) {
        boolean remove = this.middleUserChannelDirectoryService.remove(Wrappers.<MiddleUserChannelDirectory>lambdaQuery()
                .eq(MiddleUserChannelDirectory::getChannelDirectoryId, channelDirectoryDeleteToUserVo.getChannelDirectoryId())
                .in(MiddleUserChannelDirectory::getUserId, channelDirectoryDeleteToUserVo.getUserIds())
        );
        if (remove) {
            return Result.success("取消分配目录成功");
        }
        return Result.failed("取消分配目录失败");
    }

    @Override
    @Transactional
    public Result<Object> update(ChannelDirectoryUpdateVo channelDirectoryUpdateVo) {
        boolean update = this.update(Wrappers.<ChannelDirectory>lambdaUpdate()
                .set(StrUtil.isNotEmpty(channelDirectoryUpdateVo.getName()), ChannelDirectory::getName, channelDirectoryUpdateVo.getName())
                .set(StrUtil.isNotEmpty(channelDirectoryUpdateVo.getChannelDirectoryDescribe()), ChannelDirectory::getChannelDirectoryDescribe, channelDirectoryUpdateVo.getChannelDirectoryDescribe())
                .set(StrUtil.isNotEmpty(channelDirectoryUpdateVo.getParentId()), ChannelDirectory::getParentId, channelDirectoryUpdateVo.getParentId())
                .set(Objects.nonNull(channelDirectoryUpdateVo.getSort()), ChannelDirectory::getSort, channelDirectoryUpdateVo.getSort())
                .eq(ChannelDirectory::getId, channelDirectoryUpdateVo.getId())
        );
        if (update) {
            return Result.success("修改目录信息成功", null);
        }
        return Result.failed("修改目录失败");
    }

    @Override
    @Transactional
    public Result<Object> delete(ChannelDirectoryDeleteVo channelDirectoryDeleteVo) {
        //先删除目录下的所有通道
        this.middleChannelDirectoryService.remove(Wrappers.<MiddleChannelDirectory>lambdaQuery().eq(MiddleChannelDirectory::getChannelDirectoryId, channelDirectoryDeleteVo.getId()));
        this.middleUserChannelDirectoryService.remove(Wrappers.<MiddleUserChannelDirectory>lambdaQuery().eq(MiddleUserChannelDirectory::getChannelDirectoryId, channelDirectoryDeleteVo.getId()));
        this.removeById(channelDirectoryDeleteVo.getId());
        return Result.success("删除目录成功", null);
    }

}
